.TITLE DRDRV .IDENT /14.06/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; P. J. BEZEREDI 19-SEP-79 ; ; MODIFIED FOR RSX-11M-PLUS V2.1 BY: ; ; P.J. BEZEREDI ; P.J. CARR ; J. GALLANT ; ; MODIFIED BY: ; ; C. SESTOKAS 22-FEB-84 14.01 ; ; CS001 -- HCRC ERROR RECOVERY - R1 NOT SETUP ; IN DROFF ROUTINE MODIFIES LOWCORE. ; ; L. KOGAN 17-APR-84 14.02 ; ; LK001 -- CORRECT THE PROBLEM WITH ENTERING MEANINGLESS ; ENTRIES INTO ERROR LOG FILE ; ; B. S. MCCARTHY 6-AUG-85 14.03 ; ; BM368 -- ADD CONDITIONAL SKIP OF FIRST DRIVE ; NOT READY ERROR FOR POWERFAIL ; ; C SESTOKAS 19-APR-89 14.04 ; ; CS002 -- HANDLE OFFLINE UNIT UNSOLICITED INTERRUPT ; ; MODIFIED FOR RSX-11M-PLUS V4.5 BY: ; ; D. CARROLL 27-SEP-1994 14.05 ; ; DC290 -- INCLUDE SUPPORT FOR THE SHELBY DRIVE AS ; DYNAMICALLY SIZEABLE ; ; D. CARROLL 21-MAR-95 14.06 ; DC330 -- FOR SHELBY DRIVE, DO NOT PERFORM SEEK, SINCE ; THAT IS A FUNCTIONAL NO-OP FOR THE SHELBY ; ; ; ; RH11/RH70-RM02/RM03/RM05/RM80/RP07 OVERLAPPED SEEK DRIVER ; .MCALL HWDDF$,PKTDF$ HWDDF$ ;DEFINE HARDWARE REGISTERS PKTDF$ ;DEFINE I/O PACKET OFFSETS ; ; DEVICE REGISTER AND STATUS BIT DEFINITIONS ; RMCS1=0 ;CONTROL STATUS REGISTER 1 IE=100 ;INTERRUPT ENABLE TRE=40000 ;TRANSFER ERROR MCPE=20000 ;MASSBUS CONTROL PARITY ERROR DVA=4000 ;DRIVE AVAILABLE TO PORT RMWC=2 ;WORD COUNT REGISTER RMBA=4 ;BUFFER ADDRESS REGISTER RMDA=6 ;DESIRED TRACK/SECTOR REGISTER RMCS2=10 ;CONTROL STATUS REGISTER 2 DLT=100000 ;DATA LATE ERROR WCE=40000 ;WRITE CHECK ERROR UPE=20000 ;UNIBUS PARITY ERROR NED=10000 ;NONEXISTENT DISK ERROR NEM=4000 ;NONEXISTENT MEMORY ERROR PGE=2000 ;PROGRAMMING ERROR MXF=1000 ;MISSED TRANSFER ERROR MDPE=400 ;MASSBUS DATA PARITY ERROR RMDS=12 ;DRIVE STATUS REGISTER ERR=40000 ;ERROR SUMMARY BIT PIP=20000 ;POSITIONING IN PROGRESS MOL=10000 ;MEDIUM ONLINE WRL=4000 ;WRITE LOCKED DRIVE PGM=1000 ;PROGRAMMABLE PORT SELECT DPR=400 ;DRIVE PRESENT ON PORT DRY=200 ;DRIVE READY VV=100 ;VOLUME VALID OM=1 ;OFFSET MODE ACTIVE RMER1=14 ;ERROR SUMMARY REGISTER DCK=100000 ;DATA CHECK ERROR UNS=40000 ;DRIVE UNSAFE OPI=20000 ;OPERATION INCOMPLETE DTE=10000 ;DRIVE TIMING ERROR WLE=4000 ;WRITE LOCK ERROR IAE=2000 ;INVALID DISK ADDRESS AOE=1000 ;ADDRESS OVERFLOW HCRC=400 ;HEADER CRC ERROR HCE=200 ;HEADER COMPARE ERROR ECH=100 ;ECC HARD ERROR WCF=40 ;WRITE CLOCK FAILURE FER=20 ;FORMAT ERROR PAR=10 ;CONTROL BUS PARITY ERROR RMR=4 ;REGISTER MODIFY REFUSED ILR=2 ;ILLEGAL REGISTER ILF=1 ;ILLEGAL FUNCTION RMAS=16 ;ATTENTION SUMMARY REGISTER RMDBR=22 ;DATA BUFFER REGISTER RMMR=24 ;MAINTENANCE REGISTER RMDT=26 ;DRIVE TYPE REGISTER RMOF=32 ;DRIVE OFFSET REGISTER CMOD=100000 ;COMMAND MODIFIER MTD=40000 ;MOVE TRACK DESCRIPTOR FMT16=10000 ;FORMAT (1=16 BIT) ECI=4000 ;ECC INHIBIT HCI=2000 ;HEADER COMPARE INHIBIT SSEI=1000 ;SKIP SECTOR ERROR INHIBIT RMDC=34 ;DESIREDED CYLINDER NUMBER RMCC=36 ;CURRENT CYLINDER NUMBER RMER2=42 ;ERROR REGISTER 2 BSE=100000 ;BAD SECTOR ERROR SKI=40000 ;SEEK INCOMPLERE ERROR IVC=10000 ;INVALID COMMAND ERROR LSC=4000 ;LOSS OF SECTOR CLOCK ERROR LBC=2000 ;LOSS OF BIT CLOCK ERROR DVC=200 ;DEVICE CHECK ERROR SSE=40 ;SKIP SECTOR ERROR DPE=10 ;MASSBUS DATA PARITY ERROR RMEC1=44 ;ECC POSITION REGISTER RMEC2=46 ;ECC PATTERN REGISTER ; ; LOCAL EQUATED SYMBOLS ; XCT=1 ;FUNCTION HAS BEEN EXECUTED (1=YES) ERL=2 ;ERROR HAS BEEN LOGGED (1=YES) ADR=10 ;ADDRESS BITS SETUP (1=YES) SEL=20 ;PORT SELECT WAIT (1=WAITING) OFA=100 ;OFFSET ACTIVE FLAG RETRY=8. ;CONTROLLER ERROR RETRY COUNT ; ; LOCAL DATA ; DELTA: .WORD 3 ;ROTATIONAL OPTIMIZATION DELTA ; ; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLER NUMBER) ; RTTBL: .BLKW R$$M11 ;RETRY COUNT FOR CURRENT OPERATION OFFAD: .BLKW R$$M11 ;ADDRESS OF CURRENT OFFSET VALUE DGTBL: .BLKW R$$M11 ;DIAGNOSTIC PARAMETER TABLE PRMSV: .BLKW R$$M11*5 ;PARAMETER SAVE AREA FOR ERROR RECOVERY ;AND WRITE CHECK SAVWC: .BLKW R$$M11 ;SAVED WORD COUNT DLTWC: .BLKW R$$M11 ;SAVED WORD COUNT FOR DATA LATE RECOVERY $DROPT::.REPT R$$M11 ;SEEK OPTIMIZATION TABLE .WORD 1 ;0=IMPLIED SEEK; 1=ALWAYS SEEK FIRST .ENDR ; ; OFFSET POSITIONING VALUE TABLE ; OFFTB: .WORD FMT16!0 ;PLUS OFFSET .WORD FMT16!200 ;MINUS OFFSET .WORD 0 ; ; ; DIAGNOSTIC FUNCTION TABLE ; FUNTBL: .BYTE 107, IO.HMS!IQ.UMD&377 .BYTE 105, IO.BLS!IQ.UMD&377 .BYTE 115, IO.OFF!IQ.UMD&377 FUNTB: .BYTE 135, IO.DGN!IQ.UMD&377 .BYTE 151, IO.WCK!IQ.UMD&377 FUNTB1: .BYTE 171, IO.RPD!IQ.UMD&377 .BYTE 161, IO.WPD!IQ.UMD&377 .BYTE 171, IO.CER!IQ.UMD&377 .BYTE 161, IO.CEW!IQ.UMD&377 FUNTB2: .BYTE 173, IO.RDH!IQ.UMD&377 .BYTE 163, IO.WDH!IQ.UMD&377 .BYTE 175, IO.RTD!IQ.UMD&377 .BYTE 165, IO.WTD!IQ.UMD&377 FUNTB3: .BYTE 165, IO.TDD!IQ.UMD&377 FUNTBE: ; ; DRIVER DISPATCH TABLE ; DDT$ DR,R$$M11,,,,,,OPT ;GENERATE DISPATCH TABLE ;+ ; **-DRINI-RH11/RH70-RM02/RM03/RM05/RM80/RP07 DISK PACK ; CONTROLLER INITIATOR ; ; THIS IS THE DRIVER ENTRY POINT FROM THE QUEUE I/O DIRECTIVE WHEH AN ; I/O REQUEST IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO ; PROPAGATE THE EXECUTION OF THE DRIVER. IF THE SPECIFIED UNIT IS NOT ; BUSY, THEN AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE ; A RETURN TO THE CALLER IS EXECUTED. IF THE DEQUEUE ATTEMPT SUCCEEDS, ; THEN THE NEXT I/O OPERATION IS INITIATED AND A RETURN TO THE CALLER ; IS EXECUTED. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB OF THE UNIT TO BE INITIALIZED. ; ; OUTPUTS: ; ; IF THE SPECIFIED UNIT IS NOT BUSY AND AN I/O REQUEST IS WAITING ; TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER- ; ATION IS INITIATED. ;- DRINI: GTPKT$ DR,R$$M11 ;GET NEXT I/O PACKET TO PROCESS ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT: ; ; R1=ADDRESS OF THE I/O REQUEST PACKET. ; R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3=CONTROLLER INDEX. ; R4=ADDRESS OF THE STATUS CONTROL BLOCK. ; R5=ADDRESS OF THE UCB OF THE UNIT TO BE INITIALIZED. ; ; RH11/RH70-RM02/03/RP07 DISK PACK I/O REQUEST PACKET FORMAT: ; ; WD. 00 -- I/O QUEUE THREAD WORD. ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER. ; WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK. ; WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER. ; WD. 04 -- FIRST LUN WORD IN REQUESTORS TASK HEADER. ; WD. 05 -- I/O FUNCTION CODE. ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK. ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK. ; WD. 10 -- I/O STATUS BLOCK ADDRESS (DISPLACEMENT + 140000). ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE. ; WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER. ; WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER. ; WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED. ; WD. 15 -- DIAGNOSTIC SUPPLIMENTAL PARAMETER ELSE NOT USED. ; WD. 16 -- BITS <0:7> = HIGH LBN, BITS <8:15> NOT USED. ; WD. 17 -- LOW LBN OF I/O REQUEST. ; WD. 20 -- RELOCATION BIAS OF REGISTER BLOCK. ; WD. 21 -- REGISTER BLOCK ADDRESS (DISPLACEMENT + 140000). ; CLRB U.CW2+1(R5) ;RESET UNIT FLAGS CALL $VOLVD ;VALIDATE VOLUME VALID BCS 10$ ;IF CS WE FAILED TST R0 ;TRANSFER FUNCTION? BMI DRRQC ;IF MI YES JMP DRVV ;PROCESS VOLUME VALID FUNCTION 10$: CALL $IODON ;FINISH I/O BR DRINI ;TRY FOR ANOTHER PACKET ; ; REQUEST CONTROLLER FOR PROPER OPERATION. ; DRRQC: MOV S.KRB(R4),R1 ;GET CURRENT KRB ADDRESS BIT #KS.POE,K.STS(R1) ;PARALLEL OPERATIONS ENABLED? BEQ DRRQC1 ;IF EQ NO MOV S.PKT(R4),R3 ;RETRIEVE I/O PACKET ADDRESS BITB #IQ.Q,I.FCN(R3) ; EXPRESS FUNCTION ? BNE DRRQC1 ; IF NE YES BITB #IQ.UMD,I.FCN(R3) ; DIAGNOSTIC REQUEST ? BNE 20$ ; IF NE YES CMP U.PRM(R5),#<<32.*256.>+64.> ; SHELBY DRIVE? BEQ DRRQC1 ; YUP, DO NOT PERFORM SEEK OPERATION MOVB K.CON(R1),R3 ;RETREIVE CONTROLLER INDEX TST $DROPT(R3) ;WHICH SEEK METHOD? BNE 10$ ;IF NE ALWAYS SEEK FIRST BIT #KS.DIP,K.STS(R1) ;DATA TRANSFER IN PROGRESS? BEQ DRRQC1 ;IF EQ NO, START DATA TRANSFER 10$: BISB #S3.SIP,S.ST3(R4) ;SET SEEK IN PROGRESS CALL $RQCNC ;REQUEST CONTROLLER FOR CONTROL FUNCTION JMP DRINIO ; INITIATE I/O 20$: MOV #FUNTBL,R0 ; GET ADDRESS OF FUNCTION TABLE 25$: TSTB (R0)+ ; BYPASS CONTROLLER CODE CMPB (R0)+,I.FCN(R3) ; FUNCTION CODE MATCH BEQ 30$ ; IF EQ YES CMP #FUNTB,R0 ; AT END OF TABLE ? BNE 25$ ; IF NE NO BR DRRQC1 ; YES - NORMAL TRANSFER FUNCTION 30$: TSTB -(R0) ; POINT BACK TO FUNCTION CODE MOVB -(R0),U.BUF(R5) ; LOAD CONTROLLER CODE BR 10$ ; TREAT AS A SEEK DRRQC1: BICB #S3.SIP,S.ST3(R4) ;SET SEEK ALREADY COMPLETED CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER ; ; **-DRUBMP-SETUP UNIBUS ADDRESS ; ; THIS SECTION OF CODE WILL DETERMINE IF THE UNIBUS ADDRESS IS ; ALREADY IN THE FORMAT FOR THE MASSBUS CONTROLLER OR THE UNIBUS ; MAP FOR 22-BIT PROCESSORS WITHOUT RH CONTROLLERS. IT WILL ; ALSO CONVERT THE I/O FUNCTION CODE TO IT'S HARDWARE EQUIVALENT. ; ; NOTE: AT THIS POINT THE REQUESTING UNIT MUST BE THE OWNER OF ; THE CONTROLLER FOR A DATA TRANSFER. ; DRUBMP: MOV S.KRB(R4),R1 ;RETREIVE KRB ADDRESS BITB #ADR,U.CW2+1(R5);ADDRESS BITS ALREADY SETUP? BNE DRINIO ;IF NE YES BIT #FE.EXT,$FMASK ;22-BIT ADDRESSING ENABLED? BEQ 10$ ;IF EQ NO BIT #KS.MBC,K.STS(R1) ;YES, IS THIS A 22-BIT CONTROLLER? BNE 20$ ;IF NE YES CALL $STMAP ;SETUP UNIBUS MAP ADDRESS 10$: ASL U.BUF(R5) ;SHIFT BITS <4:5> TO BITS <8:9> ASL U.BUF(R5) ;... ASL U.BUF(R5) ;... ASL U.BUF(R5) ;... BIT #FE.EXT,$FMASK ;22-BIT ADDRESSING ENABLED? BEQ 20$ ;IF EQ NO CALL $MPUBM ;MAP UNIBUS TO TRANSFER 20$: BISB #ADR,U.CW2+1(R5);INDICATE ADDRESS SETUP COMPLETE MOV S.KRB(R4),R0 ;GET CURRENT KRB ADDRESS MOVB K.CON(R0),R0 ;RETRIEVE CONTROLLER INDEX MOV S.PKT(R4),R1 ;RETREIVE I/O PACKET ADDRESS MOV I.PRM+6(R1),DGTBL(R0) ;SAVE DIAGNOSTIC PARAMETERS MOV #OM,I.PRM+6(R1) ;SET OFFSET MODE INACTIVE ; ; CONVERT I/O FUNCTION CODE TO HARDWARE EQUIVALENT. ; CMPB #IO.HMS/256.,I.FCN+1(R1) ;DIGNOSTIC FUNCTION? BNE 40$ ;IF NE NO CALL DRFUN ;TEST FOR DIAGNOSTIC FUNCTION BCC 25$ ;IF CC NO BIS #SSEI,I.PRM+6(R1) ;SET SKIP SECTOR ERROR INHIBIT 25$: MOV #FUNTBL,R0 ;GET ADDRESS OF FUNCTION TABLE 30$: MOVB (R0)+,U.BUF(R5) ;LOAD CONTROLLER FUNCTION CODE CMPB (R0)+,I.FCN(R1) ;IS IT THE CORRECT CODE? BEQ 35$ ;IF EQ YES CMP #FUNTBE,R0 ;END OF FUNCTION TABLE? BNE 30$ ;IF NE NO MOV #IE.IFC&377,R0 ;ILLEGAL FUNCTION BR 45$ ;FINISH I/O 35$: CMPB #10,U.CW2(R5) ;TEST HI LBN, IS IT AN RP07? BNE 60$ ;IF NE NO CMP #FUNTB2,R0 ;IS IT A HEADER FUNCTION? BLO 60$ ;IF LO NO CMP #FUNTB3,R0 ;IS TRACK DESCRIPTOR DISPLACED? BNE 60$ ;IF FM NO BIS #MTD,I.PRM+6(R1);SET MOVE TRACK DESCRIPTOR BIT BR 60$ ; 40$: MOV #IE.IFC&377,R0 ;ASSUME ILLEGAL FUNCTION MOVB #171,U.BUF(R5) ;ASSUME READ LOGICAL FUNCTION CMPB #IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION? BHIS 50$ ;IF HIS FUNCTION IS LEGAL 45$: MOV @S.KRB(R4),R2 ;RETREIVE CSR ADDRESS MOVB U.UNIT(R5),RMCS2(R2) ;SELECT THE UNIT JMP DRFIN1 ;FINISH I/O 50$: BEQ 60$ ;IF EQ FUNCTION IS A READ MOVB #161,U.BUF(R5) ;SET WRITE LOGICAL FUNCTION 60$: MOV S.KRB(R4),R3 ;RETRIEVE KRB ADDRESS MOVB K.CON(R3),R3 ;RETRIEVE CONTROLLER INDEX MUL #5,R3 ;SETUP AN INDEX INTO ... ADD #PRMSV,R3 ;... PARAMETER SAVE AREA MOV U.BUF(R5),(R3)+ ;SAVE PARAMETERS MOV U.BUF+2(R5),(R3)+ ;... MOV U.CNT(R5),(R3)+ ;... MOV I.PRM+10(R1),(R3)+ ;... MOV I.PRM+12(R1),(R3)+ ;... ; ; **-DRINIO-INITIATE AN I/O OPERATION ; ; THIS ROUTINE WILL INITIATE EITHER A SEEK OR THE DATA TRANSFER OPER- ; ATION DEPENDING ON HOW THE CONTROLLER WAS REQUESTED. ; ; INPUTS: ; ; R4=ADDRESS OF THE SCB. ; R5=ADDRESS OF THE UCB. ; DRINIO: MOV @S.KRB(R4),R2 ;GET CSR ADDRESS MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS MOVB U.UNIT(R5),RMCS2(R2) ;SELECT UNIT ; ; DETERMINE IF DRIVE'S PORT IS SEIZED BY THIS CONTROLLER. ; MTPS #PR5 ;EXECUTE AT DEVICE PRIORITY CLR RMDS(R2) ;;;ATTEMPT TO SEIZE THE DRIVE BIT #DPR,RMDS(R2) ;;;DID THE DRIVE SEIZE? BNE 5$ ;;;IF NE YES BISB #SEL,U.CW2+1(R5);;;SET PORT SELECT WAIT FLAG MOVB S.ITM(R4),S.CTM(R4) ;;;SET TIMEOUT COUNT CLR S.FRK+2(R4) ;;;ALLOW INTERRUPTS MOVB #IE,(R2) ;;;RE-ENABLE INTERRUPTS MTPS #0 ;;;ALLOW INTERRUPTS CALLR $RLCN ;RELEASE CONTROLLER AND EXIT ; ; CHECK IF THE HEADS ARE ON THE CORRECT CYLINDER. ; 5$: MOVB #111,(R2) ;;;CLEAR SELECTED DRIVE BITB #S3.SIP,S.ST3(R4) ;;;ARE WE DOING A SEEK? BEQ 10$ ;;;IF EQ NO BITB #IQ.UMD,I.FCN(R1) ;;; DIAGNOSTIC FUNCTION ? BNE 20$ ;;; IF NE YES BIT #40,RMDT(R2) ;;;IS THIS AN RM02/03/05/80? BEQ 20$ ;;;IF EQ YES, IT HAS NO RMCC CMP RMCC(R2),I.PRM+10(R1) ;;;DO WE NEED TO SEEK? BNE 20$ ;;;IF NE YES MTPS #0 ;ALLOW INTERRUPTS JMP DRRQC1 ;GO REQUEST CONTROLLER ; ; LOAD CONTROLLER REGISTERS FOR DATA TRANSFER. ; 10$: ADD #RMCS2,R2 ;;;POINT TO SECOND CSR REGISTER MOV I.PRM+12(R1),-(R2) ;;;INSERT TRACK/SECTOR ADDRESS MOV U.BUF+2(R5),-(R2) ;;;INSERT BUFFER ADDRESS MOV U.CNT(R5),-(R2) ;;;INSERT NUMBER OF BYTES TO TRANSFER ROR (R2) ;;;CONVERT TO WORD COUNT NEG (R2) ;;;MAKE NEGATIVE WORD COUNT TST -(R2) ;;;POINT BACK TO RMCS1 CMP #IO.DGN!IQ.UMD,I.FCN(R1) ;;;DIAGNOSE MICROCODE? BNE 20$ ;;;IF NE NO MOV S.KRB(R4),R0 ;;;GET CURRENT KRB ADDRESS MOVB K.CON(R0),R0 ;;;RETRIEVE CONTROLLER NUMBER MOV DGTBL(R0),RMMR(R2) ;;;SET DIAGNOSE PARAMETERS ; ; CHECK FOR DRIVE NOT READY CONDITIONS. ; 20$: MOV #IE.DNR&377,R0 ;;;ASSUME DRIVE NOT READY MOV I.PRM+10(R1),RMDC(R2) ;;;SET DESIRED CYLINDER ADDRESS MOV RMDS(R2),R3 ;;;GET CURRENT DRIVE STATUS COM R3 ;;;COMPLEMENT STATUS BIT #MOL!DRY,R3 ;;;DRIVE READY AND ON LINE? BNE 30$ ;;;IF NE NO BIT #UNS,RMER1(R2) ;;;DRIVE UNSAFE? BEQ 70$ ;;;IF EQ NO 30$: MTPS #0 ;;;ALLOW INTERRUPTS BITB #US.SPU,U.STS(R5) ;IS DRIVE SPINNING UP? BEQ 50$ ;IF EQ NO BITB #US.VV,U.STS(R5);WAS VOLUME PREVIOUSLY MOUNTED? BEQ 35$ ;IF EQ NO JMP DRPWF0 ;YES, WAIT FOR IT TO SPIN UP 35$: JMP DRPWF1 ;WAIT JUST 15 SECONDS 50$: BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC OPERATION? BEQ 60$ ;IF EQ NO JMP DRDIAG ;PASS REGISTERS AND FINISH I/O 60$: ;REFERENCE LABEL .IF DF S2.NRD BIT #S2.NRD,S.ST2(R4) ;IS THIS FIRST DRIVE NOT READY? BNE 61$ ;IF NE NO, GO LOG ERROR BIS #S2.NRD,S.ST2(R4) ;INDICATE FIRST DRIVE NOT READY JMP DRPWF1 ;GO DO A RETRY 61$: BIC #S2.NRD,S.ST2(R4) ;CLEAR FIRST DRIVE NOT READY .ENDC ; DF S2.NRD CALL $DVERR ;LOG DRIVE NOT READY ERROR JMP DRFIN1 ;FINISH I/O 70$: BIT #VV,R3 ;;;DID VOLUME VALID STATUS CHANGE? BEQ 75$ ;;;IF EQ NO (NOTE REVERSE STATUS OF VV) BITB #US.SPU,U.STS(R5) ;;;DID WE JUST SPIN UP? BEQ 30$ ;;;IF EQ NO MOVB #123,(R2) ;;;YES, RESET VOLUME VALID BISB #US.VV,U.STS(R5);;;SET SOFTWARE VOLUME VALID 75$: BIT #S2.MAD,S.ST2(R4) ;;;MULTI-ACCESS DEVICE? BEQ 90$ ;;;IF EQ NO CMP S.KRB(R4),S.KTB(R4) ;;;IS THIS PORT 'A'? BNE 80$ ;;;IF NE NO BICB #S3.SPA,S.ST3(R4) ;;;YES, SHOW IT SPUN UP BR 85$ ;;; 80$: BICB #S3.SPB,S.ST3(R4) ;;;IT MUST BE PORT 'B' 85$: BITB #S3.SPU,S.ST3(R4) ;;;BOTH PORTS SPUN UP? BNE 95$ ;;;IF NE NO ; ; PREPARE TO START AN I/O OPERATION. ; 90$: BICB #US.SPU,U.STS(R5) ;;;RESET DRIVE SPINNING UP 95$: CLR S.FRK+2(R4) ;;;INIT FORK INTERLOCK MOVB S.ITM(R4),S.CTM(R4) ;;;SET TIMEOUT COUNT BIS #S2.ACT,S.ST2(R4) ;;;SHOW I/O IS ACTIVE BISB #XCT,U.CW2+1(R5);;;SHOW FUNCTION BEING EXECUTED BITB #S3.SIP,S.ST3(R4) ;;;SHOULD WE DO A SEEK? BEQ 105$ ;;;IF EQ NO ; ; START EXPLICIT SEEK. ; BITB #IQ.UMD,I.FCN(R1) ;;; DIAGNOSTIC FUNCTION ? BEQ 99$ ;;; IF EQ NO MOVB U.BUF(R5),(R2) ;;; LOAD POSITIONING FUNCTION BR 101$ ;;; 99$: MOVB U.PRM(R5),R3 ;;; GET SECTORS/TRACK CLR -(SP) ;;;CLEAR A WORD MOVB I.PRM+12(R1),(SP) ;;;GET DESIRED SECTOR ADDRESS SUB DELTA,(SP) ;;;SUBTRACT ROTATIONAL DELTA BPL 100$ ;;;IF PL ADJUSTMENT WAS OK ADD R3,(SP) ;;;CORRECT ADJUSTMENT IF NEGATIVE 100$: MOVB I.PRM+13(R1),1(SP) ;;;SET DESIRED TRACK ADDRESS MOV (SP)+,RMDA(R2) ;;;LOAD ADJUSTED TRACK/SECTOR ADDRESS MOVB #131,(R2) ;;;LOAD THE SEARCH FUNCTION 101$: MTPS #0 ;;; ALLOW INTERRUPTS BR DRPWF3 ;RELEASE CONTROLLER AND EXIT ; ; START DATA TRANSFER. ; 105$: MOV #FMT16,-(SP) ;;;GET FORMAT BIT BIT #40,RMDT(R5) ;;;IS IT AN RP07? BNE 106$ ;;;IF NE YES BIT #OM,I.PRM+6(R1) ;;;WAS OFFSET ACTIVE? BNE 106$ ;;;IF NE NO MOVB #115,(R2) ;;;YES, LOAD OFFSET FUNCTION 106$: BIS I.PRM+6(R1),(SP);;;SET OTHER RMOF BITS MOV (SP)+,RMOF(R2) ;;;LOAD THE OFFSET REGISTER MOV S.KRB(R4),R3 ;;;GET CURRENT KRB ADDRESS BIT #IQ.UMD,I.FCN(R1) ;;;IS IT A DIAGNOSTIC FUNCTION? BEQ 107$ ;;;IF EQ NO CMPB U.BUF(R5),#140 ;;;IS IT A UMD SEEK FUNCTION? BLO 108$ ;;;IF LO YES 107$: BIS #KS.DIP,K.STS(R3) ;;;SET DATA TRANSFER IN PROGRESS BIT #FE.EXT,$FMASK ;;;22-BIT ADDRESSING ENABLED? BEQ 110$ ;;;IF EQ NO BIT #KS.MBC,K.STS(R3) ;;;IS THIS A 22-BIT CONTROLLER? BEQ 110$ ;;;IF EQ NO MOV R3,R1 ;;;COPY KRB ADDRESS ADD K.OFF(R3),R1 ;;;POINT TO UCB TABLE MOV KE.RHB(R1),R1 ;;;RETREIVE RHBAE OFFSET ADD R2,R1 ;;;FORM AN I/O PAGE ADDRESS MOVB U.BUF+1(R5),(R1);;;SET MEMORY EXTENSION BITS 108$: MOVB U.BUF(R5),(R2) ;;;START FUNCTION BR 120$ ;;; 110$: MOV U.BUF(R5),(R2) ;;;START FUNCTION 120$: MTPS #0 ;ALLOW INTERRUPTS ; ; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES. ; DRCAN: RETURN ;NOP FOR RM02/RM03/RM05/RM80/RP07 ;+ ; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND ; CAUSES NO IMMEDIATE ACTION ON THE UNIT. THE CURRENT TIMEOUT ; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE ; SUFFICIENT TIME TO SPIN BACK UP. THE NEXT I/O REQUEST TO ANY ; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS ; THE UNIT IS ALREADY READY. ;- DRPWF: TSTB S.STS(R4) ;IS THIS UNIT CURRENTLY BUSY? BEQ DRPWF2 ;IF EQ NO DRPWF0: MOVB #15.,S.STS(R4) ;WAIT A MAXIMUM OF ONE MINUTE DRPWF1: MOVB S.ITM(R4),S.CTM(R4) ;4 SECONDS AT A TIME DRPWF2: BISB #US.SPU,U.STS(R5) ;SET UNIT SPINNING UP DRPWF3: CALLR $RLCN ;RELEASE CONTROLLER AND EXIT ;+ ; **-$DRINT-RH11/RH70-RM02/RM03/RM05/RM80/RP07 DISK PACK CONTROLLER ; INTERRUPT HANDLER ;- .ENABL LSB $DRINT::BR DRFRK ;;;ENTRY POINT FOR DATA TRANSFERS TST S.FRK+2(R4) ;;;ARE INTERRUPTS ALLOWED? BNE DRCAN ;;;IF NE NO CALL $FORK ;;;CREATE A SYSTEM PROCESS DRFRK: BITB #SEL,U.CW2+1(R5) ;WAITING FOR PORT SELECT BEQ 5$ ;IF EQ NO BICB #SEL,U.CW2+1(R5);CLEAR PORT SELECT WAIT FLAG MOV U.SCB(R5),R4 ;YES, RETREIVE SCB ADDRESS MOV S.PKT(R4),R3 ;RETREIVE I/O PACKET ADDRESS JMP DRRQC ;GO TRY AGAIN 5$: CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER MOV S.KRB(R4),R3 ;GET CURRENT KRB ADDRESS MOVB K.CON(R3),R3 ;RETREIVE CONTROLLER INDEX MOV @S.KRB(R4),R2 ;GET CSR ADDRESS MOVB U.UNIT(R5),RMCS2(R2) ;SELECT UNIT TSTB S.STS(R4) ;IS THIS UNIT BUSY? BNE 10$ ;IF NE YES MTPS #PR5 ;DISABLE INTERRUPTS MOV RMDS(R2),R0 ;;; R0 - drive status (seize drive on dual port) BIT #PGM,R0 ;;; Drive programmable (dual port)? BNE 6$ ;;; IF NE, Yes MOV #TRE!11,(R2) ;;; Clear single controller and drive BR 7$ ;;; and fork interlock. 6$: BIT #DPR,R0 ;;; Drive present (available) on port? BEQ 8$ ;;; IF EQ, No - don't do anything MOV #TRE!11,(R2) ;;; Clear controller and drive BISB #S3.DRL,S.ST3(R4) ;;; Indicate releasing drive on dual port MOVB #113,(R2) ;;; and release the drive. 7$: CLR S.FRK+2(R4) ;;; Reset fork interlock 8$: MTPS #0 ;;; and allow interrupts BR DRPWF3 ;RELEASE CONTROLLER ; ; INTERRUPT WAS FROM A BUSY UNIT. IF WE JUST DID A SEEK WE WILL ; GO AND START THE DATA TRANSFER OPERATION. IF THE DATA TRANSFER ; TERMINATED, DETERMINE WHY. IF WE ARE SPINNING UP, RETRY THE ; OPERATION. ; 10$: BITB #US.SPU,U.STS(R5) ;ARE WE SPINNING UP? BEQ 15$ ;IF EQ NO BIT #S2.MAD,S.ST2(R4) ;MULTI-ACCESS DEVICE? BEQ 12$ ;IF EQ NO CMP S.KRB(R4),S.KTB(R4) ;IS THIS PORT 'A'? BNE 14$ ;IF NE NO BITB #S3.SPA,S.ST3(R4) ;IS PORT 'A' SPINNING UP? BEQ 15$ ;IF EQ NO 12$: CALLR 100$ ;RETRY THE OPERATION 14$: BITB #S3.SPB,S.ST3(R4) ;IS PORT 'B' SPINNING UP? BNE 12$ ;IF NE YES 15$: BIT #S2.EIP,S.ST2(R4) ;ERROR ALREADY IN PROGRESS? BNE 20$ ;IF NE YES CALL DRPRM ;SET INITIAL RETRY VALUES 20$: MOV S.PKT(R4),R1 ; GET I/O PACKET ADDRESS MOV #IS.SUC&377,R0 ; ASSUME SUCESSFUL TRANSFER BITB #S3.SIP,S.ST3(R4) ; DID WE JUST DO A SEEK BEQ 30$ ; IF EQ NO BICB #S3.SIP,S.ST3(R4) ; CLEAR SEEK IN PROGRESS BITB #IQ.UMD,I.FCN(R1) ; DIAGNOSTIC FUNCTION ? BEQ 22$ ; IF EQ NO JMP DRDIAG ; IF NE YES 22$: BIT #ERR,RMDS(R2) ; ANY ERRORS DURING SEEK ? BEQ 12$ ;IF EQ NO CALL $DVERR ;LOG THE SEEK ERROR DECB RTTBL(R3) ;COUNT THIS RETRY CALL DRERL ;FINISH ERROR LOGGING 25$: MTPS #PR5 ;DISABLE INTERRUPTS MOV #TRE!11,(R2) ;;;CLEAR CONTROLLER AND DRIVE MOVB S.ITM(R4),S.CTM(R4) ;;;SET TIMEOUT COUNT CLR S.FRK+2(R4) ;;;RESET FORK INTERLOCK BIS #S2.ACT,S.ST2(R4) ;;;SHOW I/O IS ACTIVE MOVB #107,(R2) ;;;START THE RECALIBRATE MTPS #0 ;ALLOW INTERRUPTS RETURN ; ; ; INTERRUPT WAS DUE TO A DATA TRANSFER OPERATION OR A ; DIAGNOSTIC FUNCTION ; 30$: BIT #HCRC!HCE,RMER1(R2) ; HEADER CRC OR HEADER COMPARE ERROR ? BNE 36$ ;IF NE YES BIT #SSE,RMER2(R2) ;SKIP SECTOR ERROR? BEQ 36$ ;IF EQ NO BIS #SSEI,I.PRM+6(R1) ;SET SKIP SECTOR ERROR INHIBIT CALL DRCLR ;CLEAR SELECTED DRIVE ERRORS MOV RMOF(R2),-(SP) ;GET OFFSET REGISTER BIS I.PRM+6(R1),(SP) ;SET REMAINING BITS IN REGISTER MOV (SP)+,RMOF(R2) ;RE-LOAD THE OFFSET REGISTER MOV RMWC(R2),R0 ;GET NEGATIVE WORDS REMAINING BNE 32$ ;IF NE WE HAD A PARTIAL TRANSFER MOV #-1,R0 ;FAKE A PARTIAL TRANSFER 32$: ASL R0 ;CONVERT IT TO NEGATIVE BYTES ADD U.CNT(R5),R0 ;CALCULATE BYTES ACTUALLY TRANSFERED BIC #777,R0 ;GET BLOCKS ACTUALLY TRANSFERED CALL DRFUN ;TEST FOR DIAGNOSTIC FUNCTION BCC 33$ ;IF CC NO CMPB #14.,U.PRM+1(R5) ;IS IT AN RM80? BNE 33$ ;IF NE NO INC U.PRM(R5) ;INC SECTORS/TRACK 33$: CALL DRCALC ;BACKUP TO START OF BLOCK IN ERROR TST U.CNT(R5) ;LAST BLOCK TRANSFERED? BNE 34$ ;IF NE NO ADD R0,U.CNT(R5) ;YES, NORMALIZE BYTE COUNT 34$: CALL DRFUN ;TEST FOR DIAGNOSTIC FUNCTION BCC 35$ ;IF CC NO CMPB #14.,U.PRM+1(R5) ;IS IT AN RM80? BNE 35$ ;IF NE NO DECB U.PRM(R5) ;DEC SECTORS/TRACK BR 12$ ;RESTART FUNCTION 35$: INCB I.PRM+12(R1) ;INC TO NEXT SEQUENTIAL SECTOR BR 12$ ;RESTART FUNCTION 36$: BIT #SSEI,RMOF(R2) ;SKIP SECTOR ERROR INHIBIT SET? BNE 37$ ;IF NE YES BIC #SSEI,I.PRM+6(R1) ;RESET SKIP SECTOR ERROR INHIBIT 37$: CALL DRFUN ;IS IT DIAGNOSTIC FUNCTION? BCS DRDIAG ;IF CS YES 38$: BIT #70,(R2) ;RECALIBRATE FUNCTION? BEQ 80$ ;IF EQ YES BIT #TRE!MCPE,(R2) ;ANY ERRORS? BEQ 70$ ;IF EQ NO MOV RMWC(R2),R0 ;GET NEGATIVE WORDS REMAINING MOV R0,SAVWC(R3) ;SAVE IT FOR LATER USE CLR DLTWC(R3) ;ZERO SAVED DLT WC FLAG TST RMCS2(R2) ;DATA LATE ERROR? BPL 39$ ;IF PL NO MOV R0,DLTWC(R3) ;YES, SAVE REAL NEGATIVE WORDS REMAINING BNE 39$ ;IF NE WE HAD A PARTIAL TRANSFER MOV #-1,DLTWC(R3) ;DLT ON LAST WORD, FAKE A PARTIAL XFR 39$: ASL R0 ;CONVERT TO NEGATIVE BYTES ADD U.CNT(R5),R0 ;CALCULATE BYTES ACTUALLY TRANSFERED SUB #512.,R0 ;SUBTRACT OUT BLOCK IN ERROR BLE 40$ ;IF LE NO GOOD BYTES TRANSFERED BITB #ERL,U.CW2+1(R5);ERROR ALREADY IN PROGRESS? BEQ 40$ ;IF EQ NO ; ; WE GOT AN ERROR BUT SOME GOOD DATA WAS TRANSFERED. THIS ; INDICATES THAT WE RECOVERED FROM THE PREVIOUS ERROR. ; ; ; NOW LOG THE CURRENT ERROR AND DETERMINE WHAT TYPE OF ERROR ; WE HAD. ERRORS ARE BASICLY HARD, SOFT OR DATA. ; CALL DRERL ;FINISH ERROR LOGGING 40$: CALL $DVERR ;LOG DEVICE ERROR BISB #ERL,U.CW2+1(R5);SET ERROR LOGGED FLAG MOV #IE.WLK&377,R0 ;ASSUME WRITE LOCK ERROR BIT #WLE,RMER1(R2) ;WRITE LOCK ERROR? BNE 60$ ;IF NE YES MOV #IE.VER&377,R0 ;ASSUME UNRECOVERABLE ERROR BITB #IQ.X,I.FCN(R1) ;INHIBIT RETRIES? BNE 60$ ;IF NE YES TST DLTWC(R3) ;REAL DATA LATE ERROR? BNE 110$ ;IF NE YES BIT #IVC!LSC!LBC!DVC!DPE,RMER2(R2) ;HARD ERROR? BNE 60$ ;IF NE YES MOV RMER1(R2),R1 ;GET CONTENTS OF ERROR REGISTER BIT #UNS!IAE!AOE!RMR!ILR!ILF,R1 ;HARD ERROR? BNE 60$ ;IF NE YES BIT #NED!NEM,RMCS2(R2) ;HARD ERROR? BNE 60$ ;IF NE YES BIT #SKI,RMER2(R2) ;SEEK INCOMPLETE? BNE 55$ ;IF NE YES BIT #HCRC,R1 ;HEADER CRC ERROR? BNE 50$ ;IF NE YES BIT #HCE,R1 ;HEADER COMPARE ERROR? BNE 55$ ;IF NE NO BIT #FER,R1 ;FORMAT ERROR? BNE 60$ ;IF NE YES BIT #WCE!UPE!PGE!MXF!MDPE,RMCS2(R2) ;CONTROLLER ERROR? BNE DRRTRY ;IF NE YES MOV #IE.BBE&377,R0 ;ASSUME BAD BLOCK ERROR BIT #BSE,RMER2(R2) ;BAD BLOCK ERROR? BNE 60$ ;IF NE YES MOV #IE.VER&377,R0 ; ASSUME UNRECOVERABLE ERROR 50$: JMP DRECC ;CHECK FOR ECC ERRORS 55$: JMP 25$ ;TRY RECALIBRATE FUNCTION DRDIAG: CALL $CRPAS ;PASS CONTROLLER REGISTERS TO TASK CALL DRCLR ;CLEAR SELECTED DRIVE 60$: JMP DRFIN ;FINISH I/O 70$: BR DRWCHK ;GO TEST FOR A WRITE CHECK ; ; PROCESS POSITIONING OPERATION. ; 80$: MOV #IE.VER&377,R0 ;ASSUME UNRECOVERABLE ERROR BIT #ERR,RMDS(R2) ;ERRORS DURING POSITIONING? BEQ DRRTRY ;IF EQ NO CALL $DVERR ;LOG IT CLR R1 ;SHOW NO BYTES TRANSFERED JMP DRFIN1 ;FINISH I/O 100$: CALL DRCLR ;CLEAR SELECTED DRIVE CALLR DRUBMP ;RETRY ORIGINAL FUNCTION ; ; THE TRANSFER WAS STOPPED DUE TO A DATA LATE ERROR CONDITION. ; WE WILL NOW BACKUP THE WORD COUNT, BUS ADDRESS AND CYLINDER/ ; TRACK/SECTOR ADDRESS BY ONE BLOCK AND RETRY THE TRANSFER FROM ; THIS POINT. THIS IS DONE TO PREVENT THE DATA LATE CONDITION ; FROM RECURRING DUE TO A LONG TRANSFER. ; 110$: DECB RTTBL(R3) ;RETRY DATA LATE CONDITION? BLE 60$ ;IF LE NO MOV DLTWC(R3),R0 ;GET REAL NEGATIVE WORDS REMAINING ASL R0 ;CONVERT TO NEGATIVE BYTES ADD U.CNT(R5),R0 ;CALCULATE BYTES ACTUALLY TRANSFERED BIC #777,R0 ;GET BLOCKS ACTUALLY TRANSFERED CALL DRCALC ;BACKUP TO START OF BLOCK IN ERROR TST U.CNT(R5) ;DLT ERROR ON LAST BLOCK TRANSFERED? BNE 100$ ;IF NE NO ADD R0,U.CNT(R5) ;YES, NORMALIZE BYTE COUNT BR 100$ ;RESTART THE TRANSFER .DSABL LSB ;+ ; DEVICE TIMEOUT RESULTS IN THE CURRENT OPERATION BEING REPEATED ; UNLESS THE OPERATION WAS DIAGNOSTIC. TIMEOUTS ARE USUALLY CAUSED ; BY POWERFAILURE BUT MAY ALSO BE THE RESULT OF A HARDWARE FAILURE. ;- .ENABL LSB DROUT: BITB #US.SPU,U.STS(R5) ;;;IS DRIVE SPINNING UP? BEQ 15$ ;;;IF EQ NO BIT #S2.MAD,S.ST2(R4) ;;;MULTI-ACCESS DEVICE? BEQ 10$ ;;;IF EQ NO CMP S.KRB(R4),S.KTB(R4) ;;;IS THIS PORT 'A'? BNE 5$ ;;;IF NE NO, IT MUST BE PORT 'B' BITB #S3.SPA,S.ST3(R4) ;;;IS PORT 'A' SPINNING UP? BNE 10$ ;;;IF NE YES BR 15$ ;;;TIMEOUT FOR NORMAL FUNCTION 5$: BITB #S3.SPB,S.ST3(R4) ;;;IS PORT 'B' SPINNING UP? BEQ 15$ ;;;IF EQ NO, NORMAL FUNCTION 10$: DECB S.STS(R4) ;;;HAVE WE WAITED ENOUGH YET? BEQ 15$ ;;;IF EQ YES MTPS #0 ;;;ALLOW INTERRUPTS MOV S.PKT(R4),R3 ;RETREIVE I/O PACKET ADDRESS JMP DRRQC ;RETRY OPERATION 15$: INCB S.STS(R4) ;;;LEAVE CONTROLLER BUSY MTPS #0 ;;;ALLOW INTERRUPTS CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER MOV S.KRB(R4),R2 ;GET CURRENT KRB ADDRSS MOVB K.CON(R2),R3 ;RETREIVE CONTROLLER INDEX MOV (R2),R2 ;GET CSR ADDRESS MOVB U.UNIT(R5),RMCS2(R2) ;SELECT UNIT FOR ERROR LOGGING CALL $DVTMO ;LOG DEVICE TIMEOUT ; ; NOTE: THE FOLLOWING SIX INSTRUCTIONS (AND THE SUBROUTINE) DO ; NOT CHANGE THE C-BIT SETTING RETURNED FROM $DVTMO. ; BITB #SEL,U.CW2+1(R5);WAITING FOR PORT TO SELECT? BNE DRFIN1 ;IF NE YES, WE DIDN'T GET IT BITB #S3.SIP,S.ST3(R4) ;TIMEOUT DURING A SEEK? BEQ 20$ ;IF EQ NO CALL DRPRM ;RESET RETRY PARAMETERS 20$: BICB #S3.SIP,S.ST3(R4) ;ASSUME DATA TRANSFER FUNCTION BCS DRDIAG ;IF CS TIMEOUT DURING DIAGNOSTIC BITB #US.SPU,U.STS(R5) ;WAS THE DRIVE SPINNING UP? BEQ DRRTRY ;IF EQ NO MOV #IE.DNR&377,R0 ;YES, SET DRIVE NOT READY BR DRFIN ;FINISH I/O DRRTRY: MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS BICB #ERL,U.CW2+1(R5) ;CAN'T CLOSE ERRORS RETRIED FROM BEG BIT #WCE,RMCS2(R2) ;WRITE CHECK ERROR? BEQ 25$ ;IF EQ NO MOV #IE.WCK&377,R0 ;YES, SET WRITE CHECK ERROR 25$: BITB #IQ.X,I.FCN(R1) ;INHIBIT RETRIES? BNE DRFIN ;IF NE YES DECB RTTBL(R3) ;RETRY FUNCTION? BGT 40$ ;IF GT YES BR DRFIN ;FINISH I/O ; ; TEST FOR WRITE CHECK OPERATION. ; DRWCHK: BITB #IO.WLC&377,I.FCN(R1) ;WRITE FOLLOWED BY WRITE CHECK? BNE 30$ ;IF NE YES BITB #US.WCK,U.STS(R5) ;WRITE CHECK ENABLED BY MCR? BEQ DRFIN ;IF EQ NO 30$: CMPB #171,U.BUF(R5) ;WAS LAST FUNCTION A READ? BEQ DRFIN ;IF EQ YES CMPB #161,U.BUF(R5) ;WAS LAST FUNCTION A WRITE? BNE DRFIN ;IF NE NO MOV #RETRY,RTTBL(R3) ;REINITIALIZE RETRY COUNT MUL #5,R3 ;SET UP INDEX INTO ... ADD #PRMSV,R3 ;... PARAMETER SAVE AREA MOV (R3)+,U.BUF(R5) ;RESTORE PARAMETERS MOV (R3)+,U.BUF+2(R5) ;... MOV (R3)+,U.CNT(R5) ;... MOV (R3)+,I.PRM+10(R1) ;... MOV (R3)+,I.PRM+12(R1) ;... MOVB #151,U.BUF(R5) ;SET WRITE CHECK FUNCTION 40$: CALL DRCLR ;CLEAR SELECTED DRIVE CALLR DRUBMP ;START THE WRITE CHECK OPERATION .DSABL LSB ; ; **-DRFIN-FINISH I/O OPERATION ; ; THIS ROUTINE WILL SET THE ACTUAL BYTES TRANSFERED PARAMETER, THE ; ERROR LOGGING RETRY COUNTS AND CALL $IODON. THE SELECTED DRIVE ; IS RELEASED, IF REQUESTED, AND THE CONTROLLER IS RELEASED. ; ; INPUTS: ; ; R0=SUCCESS/ERROR CODE ; R2=ADDRESS OF CONTROLER CSR ; R4=ADDRESS OF THE SCB ; R5=ADDRESS OF THE UCB ; DRFIN: MOV S.PKT(R4),R3 ;GET I/O PACKET ADDRESS MOV RMWC(R2),R1 ;GET WORDS REMAINING TO TRANSFER ASL R1 ;CONVERT TO BYTES LEFT TO TRANSFER ADD I.PRM+4(R3),R1 ;CALCULATE BYTES ACTUALLY TRANSFERED DRFIN1: CALL DRCLR1 ;CLEAR SELECTED DRIVE MOV #TRE,(R2) ;NOW CLEAR THE CONTROLLER BICB #SEL,U.CW2+1(R5);CLEAR PORT SELECT WAIT FLAG MOV S.KRB(R4),R3 ;GET CURRENT KRB ADDRESS ; ; CHECK FOR ATTENTIONS AND RELEASE DRIVE. ; 10$: TSTB RMAS(R2) ;ANY ATTENTIONS PENDING? BEQ 20$ ;IF EQ NO BISB #IE,(R2) ;RE-DISPATCH TO INTERRUPT HANDLER BR 10$ ;TRY AGAIN 20$: BITB #S3.NRL,S.ST3(R4) ;SHOULD WE RELEASE THE DRIVE? BEQ 30$ ;IF EQ YES MOVB #IE,(R2) ;RE-ENABLE INTERRUPTS BR 40$ ; 30$: BISB #S3.DRL,S.ST3(R4) ;SHOW DUAL ACCESS UNIT RELEASED MOVB #113,(R2) ;RE-ENABLE INTERRUPTS AND RELEASE DRIVE 40$: MOVB K.CON(R3),R3 ;RETREIVE CONTROLLER INDEX MOVB RTTBL(R3),R2 ;GET FINAL ERROR RETRY COUNT BITB #XCT,U.CW2+1(R5);HAS A FUNCTION BEEN EXECUTED? BNE 50$ ;IF NE YES MOV #RETRY,R2 ;SET MAXIMUM RETRY COUNT 50$: BIS #RETRY*256.,R2 ;MERGE STARTING RETRY COUNT BICB #S3.SIP,S.ST3(R4) ;RESET SEEK IN PROGRESS FLAG DRFIN2: CALL $RLCN ;RELEASE CONTROLLER CALL $IODON ;FINISH I/O OPERATION JMP DRINI ;PROCESS NEXT REQUEST ; ; **-DRECC-ATTEMPT ECC CORRECTION ; ; THIS ROUTINE IS ENTERED IF A DATA ERROR IS DETECTED. IF THE ERROR ; IS CORRECTABLE, THE EXECUTIVE ECC ROUTINE IS CALLED AND THE OPERATION ; IS RESTARTED FROM WHERE THE CONTROLLER STOPPED. IF OFFSET RECOVERY ; IS REQUIRED, WE WILL DO IT. ; ; INPUTS: ; ; R1=CONTENTS OF RMER1 ; R2=ADDRESS OF CONTROLLER CSR ; DRECC: BIT #DCK!DTE!HCRC,R1;CORRECTABLE ERROR? BEQ DRRTRY ;IF EQ NO CMPB #171,U.BUF(R5) ;IS THIS A READ OPERATION? BNE DRRTRY ;IF NE NO MOV SAVWC(R3),R0 ;GET NEGATIVE # OF WORDS REMAINING ASL R0 ;CONVERT TO BYTES ADD U.CNT(R5),R0 ;CALCULATE BYTES ACTUALLY TRANSFERED BEQ DROFF ;IF EQ NONE, TRY OFFSET BIS RMER2(R2),R1 ;.OR. ERROR REGISTER 2 CMP #DCK,R1 ;ONLY DATA CHECK ERROR? BNE DROFF ;IF NE NO, TRY OFFSET MOV SAVWC(R3),-(SP) ;PUT REMAINING WORD COUNT ON STACK MOV RMEC1(R2),R1 ;GET ECC POSITION REGISTER MOV RMEC2(R2),R3 ;GET ECC CORRECTION PATTERN MOV (SP)+,R2 ;GET REMAINING WORD COUNT CALL $ECCOR ;DO ECC CORRECTION CALL DRCLR ;CLEAR SELECTED DRIVE ERRORS CALL DRPRM0 ;RESET OFFSET RECOVERY PARAMETERS CALL DRCALC ;RE-CALCULATE DISK ADDRESS MOV #IS.SUC&377,R0 ;ASSUME NO MORE WORDS TO TRANSFER TST U.CNT(R5) ;ANY MORE WORDS TO TRANSFER? BEQ DRFIN ;IF EQ NO DRREST: CALLR DRINIO ;RESTART THE TRANSFER ; ; **-DROFF-ATTEMPT OFFSET RECOVERY ; ; THIS ROUTINE IS CALLED WHENEVER WE NEED TO OFFSET THE HEADS ; SOME DISTANCE FROM TRACK CENTERLINE TO PROPERLY READ THE DATA. ; ; INPUTS: ; ; R0=NUMBER OF BYTES ACTUALLY TRANSFERED TO THIS POINT ; DROFF: BITB #OFA,U.CW2+1(R5) ;OFFSET ALREADY ACTIVE? BNE 5$ ;IF NE YES DECB RTTBL(R3) ;ANY RETRIES LEFT? BGT 5$ ;IF GT YES MOV #IE.VER&377,R0 ;SET UNRECOVERABLE ERROR JMP DRFIN ;FINISH I/O 5$: MOV S.PKT(R4),R1 ;RETRIEVE I/O PACKET ADDRESS TST R0 ;ANYTHING TRANSFERRED? BEQ 20$ ; NO BIT #ECH!DTE,RMER1(R2); HARD ECC OR DTE ERROR ? BEQ 15$ ; NO DEC R0 ;BACK UP TO THE PREVIOUS BLOCK... ; IF ON A BLOCK BOUNDARY BIC #777,R0 ; FORCE TO A BLOCK BOUNDARY ; Z-BIT SET BY BIC IF R0 IS 0 BEQ 20$ ;IF EQ NO ; ; THE TRANSFER ENDED IN AN ECC HARD ERROR BUT THERE WERE SECTORS ; TRANSFERED THAT CONTAINED GOOD DATA. SINCE THE ECC HARD ERROR COULD ; HAVE BEEN CAUSED BY A CYLINDER CROSSING, THE GOOD DATA IS SAVED ; AND THE TRANSFER IS RETRIED FROM THE POINT OF ERROR. ; 15$: CALL DRPRM0 ;RESET OFFSET RECOVERY PARAMETERS CALL DRCALC ;CALCULATE NEW PARAMETERS TST U.CNT(R5) ;LAST BLOCK TRANSFERED? BNE 20$ ;IF NE NO ADD R0,U.CNT(R5) ;YES, NORMALIZE BYTE COUNT 20$: BITB #OFA,U.CW2+1(R5) ;OFFSET ALREADY ACTIVE? BNE 30$ ;IF NE YES CALL DRPRM10 ;RESET OFFSET RECOVERY PARAMETERS BIS #OM,I.PRM+6(R1) ;SET OFFSET MODE INACTIVE MOVB #117,(R2) ;RETURN TO CENTER LINE BR DRREST ;RESTART THE TRANSFER ; ; NO GOOD DATA WAS TRANSFERED - CHECK IF OFFSET SHOULD BE CHANGED ; 30$: BIT #DTE!ECH,RMER1(R2) ;DRIVE TIMING OR HARD ECC ERROR? BNE 40$ ;IF NE YES CMP OFFAD(R3),#OFFTB;AT OFFSET ALREADY? BLO 40$ ;IF LO NO BIS #HCI,I.PRM+6(R1);YES, SET HEADER COMPARE INHIBIT 40$: DECB RTTBL+1(R3) ;CHANGE OFFSET? BGT DRREST ;IF GT NO DECB RTTBL(R3) ;COUNT EACH OFFSET AS A RETRY BIT #40,RMDT(R5) ;IS IT AN RP07? BNE DRREST ;IF NE YES ADD #2,OFFAD(R3) ;UPDATE OFFSET POINTER CMP #OFFTB+4,OFFAD(R3) ;END OF OFFSET TABLE? BEQ DRREST ;IF EQ YES MOV @OFFAD(R3),I.PRM+6(R1) ;GET NEXT OFFSET VALUE MOVB #2,RTTBL+1(R3) ;SET OFFSET RETRY COUNT BR DRREST ;RESTART THE TRANSFER ; ; **-DRERL-FINISH ERROR LOGGING FOR MID-TRANSFER ERROR ; ; THIS ROUTINE IS CALLED TO FINISH OFF THE ERROR LOGGING PROCESS ; DURING MID-TRANSFER IF WE HAVE SUCCESSFULLY RECOVERED. ; ; INPUTS: ; ; R3=CONTROLLER INDEX ; DRERL: MOV R2,-(SP) ;SAVE REGISTERS MOV R1,-(SP) ; MOVB RTTBL(R3),R2 ;GET FINAL ERROR RETRY COUNT BIS #RETRY*256.,R2 ;MERGE STARTING RETRY COUNT MOV #IS.SUC&377,R0 ;RECOVERY WAS SUCCESSFUL CALL $FNERL ;FINISH ERROR LOGGING PROCESS MOV (SP)+,R1 ;RESTORE REGISTERS MOV (SP)+,R2 ; ;FALL THRU AND RESET RECOVERY PARMS. ; ; SET RECOVERY AND RETRY PARAMETERS ; DRPRM: MOV #RETRY,RTTBL(R3);SET INITIAL RETRY COUNT DRPRM0: MOVB #16,RTTBL+1(R3) ;SET OFFSET RECOVERY COUNT DRPRM1: MOV #OFFTB-2,OFFAD(R3) ;SET OFFSET TABLE POINTER BICB #OFA,U.CW2+1(R5) ;CLEAR OFFSET ACTIVE FLAG RETURN ; ; ; **-DRCALC-CALCULATE UPDATED DISK ADDRESS ; ; THIS ROUTINE WILL CALCULATE THE NEW DISK AND BUFFER ADDRESSES ; BASED ON THE NUMBER OF BYTES ACTUALLY TRANSFERED. ; ; INPUTS: ; ; R0=BLOCKS ACTUALLY TRANSFERED. ; ; OUTPUTS: ; ; R0=UNCHANGED IF U.CNT(R5)=0 ; I.PRM+10(R1)=NEW CYLINDER ADDRESS ; I.PRM+12(R1)=NEW TRACK SECTOR ADDRESS ; DRCALC: SUB R0,U.CNT(R5) ;REDUCE BYTES REMAINING TO TRANSFER BEQ 30$ ;IF EQ NONE LEFT ADD R0,U.BUF+2(R5) ;UPDATE STARTING BUFFER ADDRESS ADCB U.BUF+1(R5) ;AND THE MEMORY EXTENSION BITS BIT #FE.EXT,$FMASK ;IS 22-BIT ADDRESSING ENABLED? BEQ 5$ ;IF EQ NO MOV S.KRB(R4),R1 ;RETREIVE KRB ADDRESS BIT #KS.MBC,K.STS(R1) ;IS THIS A 22-BIT MASSBUS DEVICE? BNE 5$ ;IF NE YES ADD K.OFF(R1),R1 ;POINT TO UMR AREA+2 ADD R0,-(R1) ;CALCULATE NEW REAL ADDRESS ADCB -(R1) ;... 5$: MOV S.PKT(R4),R1 ;RETREIVE I/O PACKET ADDRESS SWAB R0 ;CALCULATE NUMBER OF SECTORS TRANSFERED ASR R0 ; ADD I.PRM+12(R1),R0 ;UPDATE TRACK/SECTOR ADDRESS TST -(SP) ;GET A WORKING REGISTER 10$: CLR (SP) ;CLR THE WORKING REGISTER FOR THE LOOP CMPB U.PRM(R5),R0 ;SECTOR OVERFLOW? BHI 20$ ;IF HI NO MOVB U.PRM(R5),(SP) ;COPY SECTORS/TRACK SUB (SP),R0 ;SUBTRACT A TRACKS WORTH OF SECTORS ADD #1*256.,R0 ;ADD IN A TRACK MOV U.PRM(R5),(SP) ;GET TRACKS AND SECTORS CLRB (SP) ;ISOLATE ONLY TRACKS/CYLINDER CMP (SP),R0 ;TRACK OVERFLOW? BHI 10$ ;IF HI NO SUB (SP),R0 ;NORMALIZE TRACK ADDRESS INC I.PRM+10(R1) ;UPDATE CYLINDER ADDRESS BR 10$ ; 20$: MOV R0,I.PRM+12(R1) ;SET UPDATED TRACK/SECTOR ADDRESS TST (SP)+ ;PRUNE STACK 30$: RETURN ; ; ; **-DRVV-PROCESS VOLUME VALID FUNCTIONS ; ; HERE WE WILL PROCESS VOLUME VALID FUNCTIONS. IF THE FUNCTION IS ; SET VOLUME VALID WE WILL SET THE HARDWARE VOLUME "VV" BIT. IF THE ; FUNCTION IS CLEAR VOLUME VALID WE WILL DO NOTHING AS THE HARDWARE ; CANNOT SPIN THE DRIVE DOWN. IF THE FUNCTION IS A VOLUME VALID NOP, ; WE WILL SIZE THE DISK BY PASSING THE CONTROLLER REGISTERS BACK TO ; THE CALLER. ; ; INPUTS: ; ; R4=ADDRESS OF THE SCB. ; R5=ADDRESS OF THE UCB ; DRVV: CALL $RQCND ;REQUEST CONTROLLER FOR DATA TRANSFER MOV #IS.SUC&377,R0 ;SET SUCCESSFUL OPERATION MOV @S.KRB(R4),R2 ;RETREIVE CSR ADDRESS MOVB U.UNIT(R5),RMCS2(R2) ;SELECT THE UNIT MOV S.PKT(R4),R1 ;RETREIVE I/O PACKET ADDRESS CALL DRCLR ;CLEAR SELECTED DRIVE BIT #NED,RMCS2(R2) ;DOES THE DRIVE EXIST? BEQ 5$ ;IF EQ YES TST I.PRM+2(R1) ; SIZE THE DISK ? BMI 4$ ; IF MINUS THEN YES CALL $DVERR ;LOG THE ERROR 4$: ; REFFERENCE LABEL MOVB #TRE/256.,RMCS1+1(R2) ;CLEAR THE CONTROLLER MOV #IE.SZE&377,R0 ;UNABLE TO SIZE UNIT BICB #US.VV,U.STS(R5);RESET VOLUME VALID JMP DRFIN2 ;EXIT 5$: TST I.PRM+2(R1) ;SIZE THE DISK? BPL 10$ ;IF PL NO CMPB RMDT(R2),#47 ; IS THIS A SHELBY? BNE 6$ ; IF NE, NOPE ... BIT #MOL,RMDS(R2) ; DO WE HAVE MOL BEQ 6$ ; IF EQ, NOPE, DON'T IDENT ... MOVB #47,(R2) ; LOAD THE FUNCTION 6$: CALL $CRPAS ;PASS CONTROLLER REGISTERS TO CALLER BR 15$ ; 10$: BIT #VV$SET,I.PRM+2(R1) ;SET VOLUME VALID? BEQ 25$ ;IF EQ NO MOV RMDS(R2),R1 ;GET DRIVE STATUS REGISTER COM R1 ;TOGGLE THE BITS BIT #MOL!DRY,R1 ;IS THE DRIVE READY AND ONLINE? BNE 20$ ;IF NE NO CMPB RMDT(R2),#47 ; IS THIS A SHELBY? BNE 13$ ; IF NE, NOPE ... CONTINUE MOVB #47,(R2) ; ISSUE THE IDENT FUNCTION 12$: CMPB (R2),#246 ; FUNCTION COMPLETED? BNE 12$ ; IF NE, NOPE, PAUSE A MOMENT MOV R0,-(SP) ; SAVE CURRENT STATUS CODE MOV RMCC(R2),R0 ; GET THE HIGHEST CYLINDER INC R0 ; BUMP THE HIGHEST CYLINDER MOV R0,U.PRM+2(R5) ; UPDATE THE GEOMETRY MUL #<64.*32.>,R0 ; CALCULATE THE HIGHEST LBN MOVB R0,U.CW2(R5) ; LOAD THE HIGH ORDER LBN MOV R1,U.CW3(R5) ; AND THE LOW ORDER DRIVE SIZE MOV (SP)+,R0 ; RESTORE R0 13$: MOVB #23,(R2) ;ISSUE PACK ACK TO SET VV 15$: JMP DRFIN1 ;EXIT 20$: MOV #IE.DNR&377,R0 ;DRIVE NOT READY ERROR CODE BICB #US.VV,U.STS(R5);RESET VOLUME VALID BR 15$ ;EXIT 25$: BIT #VV$UNL,I.PRM+2(R1) ; UNLOAD DRIVE REQUESTED? BEQ 15$ ; IF EQ, NOPE, FINISH UP CMPB RMDT(R2),#47 ; IS THIS A SHELBY DRIVE? BNE 15$ ; IF NE, NOPE, DON'T TRY UNLOAD BIT #MOL,RMDS(R2) ; IS MEDIA LOADED? BEQ 15$ ; NOPE, FINISH UP ... MOVB #3,(R2) ; ISSUE THE UNLOAD FUNCTION BR 15$ ; AND FINISH UP ; ; **-DRCLR-CLEAR DRIVE OR SUB-SYSTEM ; **-DRCLR1-ALTERNATE ENTRY TO CLEAR DRIVE W/O INTERRUPT ENABLE ; ; ISSUE A DRIVE CLEAR FUNCTION UNLESS THE SELECTED DRIVE/CONTROLLER ; IS HUNG, THEN ISSUE SUB-SYSTEM CLEAR. ; ; INPUTS: ; ; R2=CSR ADDRESS ; R5=UCB ADDRESS ; ; OUTPUTS: ; ; SELECTED DRIVE IS CLEARED ; .ENABL LSB DRCLR: TSTB (R2) ;IS THE CONTROLLER READY? BPL 10$ ;IF PL NO BIT #1,(R2) ;IS GO BIT SET? BNE 10$ ;IF NE YES MOVB #111,(R2) ;NO, ISSUE DRIVE CLEAR RETURN ;AND EXIT DRCLR1: TSTB (R2) ;IS THE CONTROLLER READY? BPL 10$ ;IF PL NO BIT #1,(R2) ;IS GO BIT SET? BNE 10$ ;IF NE YES MOVB #11,(R2) ;NO, ISSUE DRIVE CLEAR RETURN ;AND EXIT ; ; NOTE: ; ; THE FOLLOWING INSTRUCTION WILL CAUSE ALL I/O ON OTHER UNITS TO ; ABORT. THIS IS OK BECAUSE THE TIMEOUT FACILITY SHOULD CATCH THEM. ; 10$: BIS #40,RMCS2(R2) ;ISSUE SUB-SYSTEM CLEAR MOVB U.UNIT(R5),RMCS2(R2) ;RE-SELECT THE DRIVE RETURN ;AND EXIT .DSABL LSB ; ; **-DRFUN-PROCESS DIAGNOSTIC FUNCTION TESTING ; ; DETERMINE IF THE SPECIFIED FUNCTION IS A DIAGNOSTIC OR NOT. ; TWO EXCEPTIONS: IO.CER AND IO.CEW ; ; INPUTS: ; R1=ADDRESS OF I/O PACKET ; ; OUTPUTS: ; C/S=DIAGNOSTIC FUNCTION (EXCEPT AS NOTED) ; C/C=NORMAL FUNCTION ; DRFUN: CMPB #IO.CER!IQ.UMD&377,I.FCN(R1) ;IS IT READ CE CYLINDER? BEQ 10$ ;IF EQ YES CMPB #IO.CEW!IQ.UMD&377,I.FCN(R1) ;IS IT WRITE CE CYLINDER? BEQ 10$ ;IF EQ YES BIT #IQ.UMD,I.FCN(R1) ;IS IT A DIAGNOSTIC FUNCTION? BEQ 10$ ;IF EQ NO SEC ;YES, SET CARRY RETURN ;EXIT 10$: CLC ;NO, CLEAR CARRY RETURN ;EXIT ;+ ; **-DRCHK-VALIDATE AND CONVERT THE LBN ; ; THIS ROUTINE IS CALLED FROM $DRQRQ TO DO LBN PROCESSING ; FOR DEVICES WHICH SUPPORT QUEUE OPTIMIZATION. IF BLKC2 ; DETECTS AN ERROR IT WILL RETURN TO THE CORRECT PLACE IN ; $DRQRQ AFTER CALLING $IOALT. ; ; INPUTS: ; ; R1=I/O PACKET ADDRESS ; R5=UCB ADDRESS ; ; OUTPUTS: ; ; IF THE CHECKS SUCCEEDS, THEN THE LBN IN THE PACKET ; IS REPLACED BY THE CYLINDER/TRACK/SECTOR. R1 IS PRESERVED. ; ; IF THE CHECKS FAILS, THEN $IOALT IS ENTERED WITH A FINAL ; STATUS OF IE.BLK AND A RETURN TO THE CORRECT PLACE IN ; $DRQRQ IS EXECUTED. ; ; ; NOTE: ALL FUNCTIONS PUT INTO THE DRIVER QUEUE ARRIVE HERE. ; THESE INCLUDE IO.ATT, IO.DET, AND ACP FUNCTIONS. ;- DRCHK: MOV I.FCN(R1),-(SP) ;PUT THE FUNCTION ONTO THE STACK BIC #7,(SP) ;CLEAR THE SUBFUNCTION BITS CMPB #IO.ATT/256.,1(SP) ;IS IT ATTACH BEQ 55$ ;IF EQ YES - LEAVE IT ALONE CMPB #IO.DET/256.,1(SP) ;IS IT DETACH BEQ 55$ ;IF EQ YES - LEAVE IT ALONE CMP #IO.STC,(SP) ;IS IT SET CHARACTERISTICS? BEQ 55$ ;IF EQ YES - LEAVE IT ALONE TST (SP)+ ;CLEAN THE STACK BIT #IQ.UMD,I.FCN(R1) ;IS IT A DIAGNOSTIC FUNCTION? BNE 30$ ;IF NE YES CALL $BLKC2 ;CHECK LOGICAL BLOCK NUMBER CMPB #IO.WLB/256.,I.FCN+1(R3) ;WRITE FUNCTION? BNE 40$ ;IF NE NO BITB #IO.WLT&377,I.FCN(R3) ;WRITE LAST TRACK FUNCTION? BNE 40$ ;IF NE YES CMP U.PRM(R5),#<<32.*256.>+64.> ; SHELBY DRIVE? BEQ 40$ ; YUP, NOT A LAST TRACK DEVICE CLR R0 ;GET READY FOR THE BISB BISB U.PRM(R5),R0 ;GET SECTORS/TRACK ADD R0,I.PRM+12(R3) ;INCREMENT BLOCK # BY ONE TRACK ADCB I.PRM+10(R3) ;AND THE CARRY MOV R3,R1 ;RESTORE PACKET ADDRESS FOR $BLKC2 CALL $BLKC2 ;SEE IF WRITE IS TO BAD SECTOR FILE CLR R1 ;GET READY FOR THE BISB BISB U.PRM(R5),R1 ;GET SECTORS/TRACK SUB R1,R0 ;CORRECT THE BLOCK NUMBER SBCB R2 ;AND THE HIGH BLOCK NUMBER BR 40$ ;CONTINUE 30$: MOV R1,R3 ;COPY POINTER TO I/O PACKET ADD #I.PRM+11,R1 ;POINT PAST HIGH PART OF LBN CLRB (R1)+ ;CLEAR EXCESS BYTE MOV (R1),R0 ;GET LOW PART OF LBN MOV -(R1),R2 ;GET HIGH PART OF LBN MOV R3,R1 ;RESTORE THE I/O PACKET POINTER CALL DRFUN ;TEST FOR DIAGNOSTIC FUNCTION BCC 40$ ;IF CC NO CMPB #14.,U.PRM+1(R5) ;IS IT AN RM80? BNE 40$ ;IF NE NO INCB U.PRM(R5) ;INC SECTORS/TRACK 40$: CALL $CVLBN ;CONVERT LOGICAL BLOCK NUMBER MOV R2,I.PRM+10(R3) ;SAVE DESIRED CYLINDER ADDRESS SWAB R1 ;SWAP TRACK TO HIGH BYTE BIS R1,R0 ;MERGE TRACK WITH SECTOR MOV R0,I.PRM+12(R3) ;SAVE DESIRED TRACK AND SECTOR ADDRESS MOV R3,R1 ;RETRIEVE I/O PACKET ADDRESS CALL DRFUN ;TEST FOR DIAGNOSTIC FUNCTION BCC 50$ ;IF CC NO CMPB #14.,U.PRM+1(R5) ;IS IT AN RM80? BNE 50$ ;IF NE NO DECB U.PRM(R5) ;DEC SECTORS/TRACK 50$: RETURN ;EXIT 55$: TST (SP)+ ;CLEAN THE STACK BR 50$ ;AND EXIT .END